package org.example.acl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.*;
import org.springframework.security.core.Authentication;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@Slf4j
class MyPermissionEvaluator implements PermissionEvaluator {

    @Autowired
    private AclService aclService;

    @Autowired
    private UserRepository userRepository;

    @Override
    public boolean hasPermission(
            Authentication authentication,
            Object targetDomainObject,
            Object permission) {
        log.info("#hasPermission#1# authentication={} targetDomainObject={} permission={}", authentication.getName(), targetDomainObject, permission);
        return hasPermission(authentication,
                ((User) targetDomainObject).getId(),
                "user",
                permission);
    }

    @Override
    public boolean hasPermission(
            Authentication authentication,
            Serializable targetId,
            String targetType,
            Object permission) {
        log.info("#hasPermission#2# authentication={} targetId={} targetType={} permission={}", authentication.getName(), targetId, targetType, permission);
        ObjectIdentity oid = new ObjectIdentityImpl(targetType, targetId);
        Acl acl = aclService.readAclById(oid);
        if (acl == null) {
            return false;
        }
        User user = userRepository.getByName(authentication.getName());
        List<Sid> sids = List.of(new PrincipalSid("user:" + user.getId()));
        List<Permission> permissions = new ArrayList<>();
        if (permission.equals("read")) {
            permissions.add(BasePermission.READ);
        }
        return acl.isGranted(permissions, sids, false);
    }
}
